
#ifndef __VSFAV_H_INCLUDED__
#define __VSFAV_H_INCLUDED__

#include "stream/vsfav_stream.h"

enum vsfaudio_control_t
{
	VSFAUDIO_CONTROL_UNDEFINED = 0,

	// feature unit
	VSFAUDIO_MUTE_CONTROL = 1,
	VSFAUDIO_VOLUME_CONTROL = 2,
	VSFAUDIO_BASS_CONTROL = 3,
	VSFAUDIO_MID_CONTROL = 4,
	VSFAUDIO_TREBLE_CONTROL = 5,
	VSFAUDIO_GRAPHIC_EQUALIZER_CONTROL = 6,
	VSFAUDIO_AUTOMATIC_GAIN_CONTROL = 7,
	VSFAUDIO_DELAY_CONTROL = 8,
	VSFAUDIO_BASS_BOOST_CONTROL = 9,
	VSFAUDIO_LOUDNESS_CONTROL = 10,

	// processing unit
};

struct vsfav_control_t
{
	uint8_t control;
	uint8_t busy : 1;
	uint8_t len;

	union
	{
		void *pbuf;
		uint8_t uval8;
		int8_t ival8;
		uint16_t uval16;
		int16_t ival16;
		uint32_t uval32;
		int32_t ival32;
		bool enable;
	};

	struct vsflist_t list;
};

struct vsfav_control_list_t
{
	struct vsfsm_sem_t update_sem;
	uint32_t num;
	struct vsflist_t list;
};

enum vsfav_unit_type_t
{
	VSFAV_STREAM_INPUT,
	VSFAV_STREAM_OUTPUT,
	VSFAV_INPUT,
	VSFAV_OUTPUT,
	VSFAV_FEATURE,
	VSFAV_MIXER,
	VSFAV_SELECTOR,
	VSFAV_PROCESSING,
};

struct vsfav_unit_feature_t
{
	struct vsfav_control_list_t control;
};

struct vsfav_unit_mixer_t
{
	struct vsfav_control_list_t control;
};

struct vsfav_unit_selector_t
{
	struct vsfav_control_list_t control;
};

struct vsfav_unit_processing_t
{
	struct vsfav_control_list_t control;
};

struct vsfav_unit_input_stream_t
{
	struct vsfav_stream_t av_stream;
};

struct vsfav_unit_output_stream_t
{
	struct vsfav_stream_t av_stream;
};

struct vsfav_unit_t;
struct vsfav_input_t
{
	uint8_t number;
	uint8_t valid_number;
	struct vsfav_unit_t *array[0];
};

struct vsfav_unit_t
{
	uint8_t id;
	enum vsfav_unit_type_t type;
	void *priv;

	struct vsfav_unit_t *next;
	struct vsfav_input_t *input;

	union
	{
		struct vsfav_unit_feature_t *feature;
		struct vsfav_unit_mixer_t *mixer;
		struct vsfav_unit_input_stream_t *input_stream;
		struct vsfav_unit_output_stream_t *output_stream;
		struct vsfav_unit_selector_t *selector;
		struct vsfav_unit_processing_t *processing;
	};
};

struct vsfav_topology_t
{
	uint32_t num_of_outputs;
	struct vsfav_unit_t *output_units;
	uint32_t num_of_inputs;
	struct vsfav_unit_t *input_units;

	uint32_t num_of_units;
	struct vsfav_unit_t *units[0];
};

struct vsfav_dev_t
{
	// topology MUST be the last member for variable size
	struct vsfav_topology_t topology;
};

void vsfav_unit_add_input(struct vsfav_unit_t *unit, struct vsfav_unit_t *input);
struct vsfav_unit_t *vsfav_get_unit_byid(struct vsfav_dev_t *dev, uint8_t id);

#endif		// __VSFAV_H_INCLUDED__
